﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAPICodePack.Shell;
using FireZone.DataStructure;
using System.IO;
using System.ComponentModel;
using Microsoft.WindowsAPICodePack.Shell.PropertySystem;
using System.Runtime.InteropServices;
using FireZone.NativeWMDMInteface;
using System.Threading;
using System.Threading.Tasks;
using System.Reflection;

namespace FireZone
{
    internal static class CommonExtension
    {
        public static T MarshalAs<T>(this byte[] sourceValue, int startIndex = 0)
        {
            IntPtr ptr = Marshal.AllocHGlobal(sourceValue.Length - startIndex);
            try
            {
                Marshal.Copy(sourceValue, startIndex, ptr, sourceValue.Length - startIndex);
                return (T)Marshal.PtrToStructure(ptr, typeof(T));
            }
            finally
            {
                Marshal.FreeHGlobal(ptr);
            }
        }

        public static byte[] MarshalAs<T>(this T t)
        {
            IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(t));
            try
            {
                Marshal.StructureToPtr(t, ptr, true);
                var ret = new byte[Marshal.SizeOf(t)];
                Marshal.Copy(ptr, ret, 0, ret.Length);
                return ret;
            }
            finally
            {
                Marshal.FreeHGlobal(ptr);
            }
        }

        public static void SafeCloseStream<T>(this T stream) where T:Stream
        {
            if (stream != null) stream.Close();
        }

        public static void SafeCancelCancellationTokenSource(this CancellationTokenSource tokenSource)
        {
            if (tokenSource != null) tokenSource.Cancel();
        }

        public static void SafeDispose<T>(this T disp) where T: IDisposable
        {
            if (disp != null) disp.Dispose();
        }

        public static void SafeDisposeAll<T>(this IEnumerable<T> dispList) where T: IDisposable
        {
            if (dispList != null) dispList.Select((a) => { a.SafeDispose(); return a; });
        }       

        public static string FindClassStaticFieldNameByValue<T>(this Type t, T v)
        {
            FieldInfo[] fi = t.GetFields(BindingFlags.Static|BindingFlags.Public|BindingFlags.GetField);

            FieldInfo fiFind = fi.FirstOrDefault((f) => { return v.Equals((T)f.GetValue(null)); });
            if(fiFind == default(FieldInfo))
            {
                return "UNKNOWN<" + v.ToString() + ">" ;
            }
            else
            {
                return fiFind.Name;
            }
        }
    }
}
